Java 中的正则表达式

第七篇关于 Java 的笔记.

一. 正则表达式的历史

//看不懂, 不明觉厉

(正则表达式可能就是一个用来匹配字符串的 “模式串”)

二. 正则表达式的组成

1. 普通字符和元字符

  • 普通字符也就是平时使用的字符, 它们出现的时候就代表它们本身
  • 元字符是具有特殊含义的字符, 有些元字符可以代表某些字符, 比如 . 可以匹配任意字符

2. 字符串字面量(literal)匹配

  • /abc/ 匹配 “abc”, 但不匹配 “abc d”, 这说明, 空格会影响到字符串匹配.
  • 当一个文档有多个 “/abc/“ 匹配的字符串时, 标准模式选择最前面那个, 如果选择了 global 模式, 则会选中所有的字符串.

3. “元字符”匹配

  • “元字符”即有着特殊含义的字符, 有: \ . * + - {} [] ^ $ | ? () : ! =
  • . 可以匹配任意单个字符, 在 s 模式下, 还可以匹配 “h换行t”.

4. 使用转义法匹配”元字符”

  • 比如想匹配 . 就要加上 \ 变成 \.

5. 匹配特殊字符

含义 表格形式
空格 在表达式直接敲空格就行了
Tab \t
回车, 换行 \r(回车), \n(换行), \r\n(回车换行)
ESC \e
ASC 码字符 比如 0xA9, 正则表达式要写成: \xA9
Unicode 字符 比如 4e00, 正则表达式要写成: \u4e00

6. 定义可选字符集合

  • 在正则表达式中都是一个一个字符来匹配的, 这里定义的可选字符集合, 也是匹配一个字符而已.
  • 定义可选字符集合使用: []
    • 可定义一个字符区间
  • [0-9] 表示 10 个阿拉伯数字, [A-Z]表示大写的 26 个字符
  • 在 [] 中, “]”, “-“, “^” 和 “\” 需要转义. 比如需要匹配 ]或者) : [\])]

7. 字符集合的简写

符号 含义
\d 匹配单个数字字符, 相当于[0-9]
\D 匹配单个非数字字符, 相当于 [^0-9]
\w 匹配单个数字, 大小写字母字符, 相当于 [0-9a-zA-Z]
\W 匹配单个非数字, 大小写字母字符, 相当于 [^0-9a-zA-Z]
\s 匹配空白符, 空白符包括 Tab, 回车(\r), 换行(\n)
\S 匹配空白符之外的字符

三. 处理重复

遇到单个或者某一类字符重复问题, 就要看下面的符号表了, 这些符号用来确定前面一个字符出现的次数, 这些符号也被称为 “贪婪量词”.

1. 符号表

符号 含义
* 指定字符出现 0 或 n 次
+ 指定字符出现 1 或 n 次
? 指定字符出现 0 或 1 次

2. 指定次数的重复

  • 使用 {min, max} 指定重复次数
  • min 是必填的, 最小是 0, 表示重复次数
  • max 是可选的, 表示最多重复次数. 如 {3,} 表示至少三个

四. 分组

  • 使用 () 可以把若干个字符当成一个整体处理.

五. 多选一

  • 使用 | 从多个可选项中选择一个. 左边的选项拥有高的优先级

六. 字符串的开头和结尾

1. 符号表

符号 含义
^ 指定起始字符
$ 指定结束字符

2. Singleline 和 Multline

  • ^ 和 $ 的 Singleline 模式是正则匹配表达式引擎的默认设置, 也就是说多行文本, 只针对第一行和最后一行的字符进行匹配, 中间的行会自动无视.
  • 如果希望 ^ 和 $ 在匹配时也能处理中间的行, 则需要进入 “Multline anchors” 模式. (Java 中 Pattern.MULTILINE)

七. 边界处理

  • \b 匹配单词的边界位置
  • \B 所有不是单词边界的位置

八. 反向引用

  • 利用 () 定义了多个字符串组时, 可以用 \1 到 \9 来引用它们. 比如: (apple) to \1
  • 由于最多有 9 个反向引用, 所以可以使用 ?: 指明特定字符组合不参加反向引用. 比如: (?:oranges) and (apple) to \1

九. 断言

我们可以使用 ?= 给字符组加上判断条件, 从而对匹配结果施加影响.

  • (?=seashore)sea 先看看字符串是否有 seashore 出现, 为真时, 回到开头, 再匹配后面的内容 sea, 两者都为 true 则匹配结果为真.
  • sea(?=shore) 先匹配 sea 在看后面是否跟着 shore (无需回到起点), 都为 true 则结果为匹配.
  • 注意出现 “?=” 后面的正则表达式中的字符不会出现在最终匹配的字符串中, 它们仅仅用来影响匹配过程.

十. 多断言判断

  • 利用前置 “?=” 可以回到起点的特点, 我们可以对一个字符串依据多个标准进行匹配判断. 比如: (?=^[0-5-]+$)(?=.*4321) 含义: 可以是 - 或者数字, 数字必须是 0-5 之间, 而且必须有 4321 出现.

十一. “否”断言

  • “?=” 用于定义为 true 的条件, “?!” 则用于定义为 false 的条件. 例如, 要求字符串中不包容 4321: (?!.*4321)

十二. 自动回退的断言(看不懂 2017年12月10日 12:42:06)

  • 默认情况下, 正则表达式引擎在处理 “?=” 和 “?!” 时都是从当前位置开始, 仅在必要时回退.
  • 但有些情况下, 明确通知正则表达式引擎 “回退” 则会带来更高的效率.
  • 编写自动回退的断言很简单, 只需要使用 “?<=” 和 “?\<!“ 就行了.
  • 例如: /(?<=base)ball/ 告诉正则表达式引擎, 如果发现了 ball 就回退回去看前面是不是 base, 如果确实是 base 则匹配.

十三. 关于断言

  • 要注意断言并不影响正则表达式引擎的 “位置”, 引擎发现一个断言之后, 它评估它的值, 之后, 会回到评估断言之前的位置.
  • 不同的编程语言和平台可能并不支持特定的语法, 需要查询相应文档或进行师弟测试.